package terms;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * Class which represents the calls of the function.
 * Mar 29, 2012 Ecole des Mines de Nantes
 * Major in Information and Communications Systems Engineering.
 * @author Pierre Reliquet, Simon Devineau
 */
public class Call extends AbstractTerm {
    /**
     * The variable which represents the function.
     */
    private Function                 function;
    /**
     * The arguments of the function.
     */
    private Collection<AbstractTerm> arguments = new ArrayList<AbstractTerm>();

    /**
     * The constructor when there is just a function with arity 0.
     * @param aFunction
     *            the zero-arity function.
     */
    public Call(final Function aFunction) {
        super();
        this.function = aFunction;
    }

    /**
     * The constructor which specifies the function and its arguments.
     * @param aFunction
     *            the function
     * @param terms
     *            the arguments of the function
     */
    public Call(final Function aFunction, final Collection<AbstractTerm> terms) {
        super();
        this.function = aFunction;
        this.arguments = terms;
    }

    /**
     * Add aTerm to the list.
     * @param aTerm
     *            the element to add
     */
    public void addTerm(final AbstractTerm aTerm) {
        this.arguments.add(aTerm);
    }

    /**
     * @param anObject
     *            the object to verify the equality.
     * @return true if anObject is a call and equal to this
     */
    @Override
    public boolean equals(final Object anObject) {
        boolean toReturn = false;
        if (anObject instanceof Call) {
            final Call aCall = (Call) anObject;
            if (aCall.getFunction().equals(this.getFunction())) {
                toReturn = aCall.getArguments().equals(this.getArguments())
                        && aCall.getRest().equals(this.getRest())
                        && aCall.getFunction().equals(this.getFunction());
            }
        }
        return toReturn;
    }

    /**
     * @return the arguments
     */
    public final Collection<AbstractTerm> getArguments() {
        return this.arguments;
    }

    /**
     * @return the function
     */
    public final Function getFunction() {
        return this.function;
    }

    /**
     * @return the length
     */
    @Override
    public int getLength() {
        return 1 + this.getFunction().getArity();
    }

    /**
     * @return the name of the function called
     */
    @Override
    public String getName() {
        return this.function.getFunctionName();
    }

    /**
     * @return the rest of the elements
     */
    @Override
    public Collection<AbstractTerm> getRest() {
        return this.arguments;
    }

    /**
     * @return the hashCode of the function called
     */
    @Override
    public int hashCode() {
        return this.getFunction().hashCode() + this.getArguments().hashCode();
    }

    /**
     * @return true if there is a rest
     */
    @Override
    public boolean isRest() {
        return this.function.getArity() != 0;
    }

    /**
     * @param anArguments
     *            the arguments to set
     */
    public final void setArguments(final Collection<AbstractTerm> anArguments) {
        this.arguments = anArguments;
    }

    /**
     * @param aFunction
     *            the function to set
     */
    public final void setFunction(final Function aFunction) {
        this.function = aFunction;
    }

    /**
     * @return the String representation of the call
     */
    @Override
    public String toString() {
        final StringBuffer buffer = new StringBuffer(this.getName() + "(");
        for (final Iterator<AbstractTerm> current = this.arguments.iterator(); current
                .hasNext();) {
            buffer.append(current.next().toString());
            if (current.hasNext()) {
                buffer.append(',');
            }
        }
        buffer.append(')');
        return buffer.toString();
    }
}
